
require 'rubygems'
require 'win32console'
require 'inifile'
require 'socket'
include Win32::Console::ANSI

SCRIPT_ID = 3
SCRIPTS_ROOT = 'C:\VAPC\vaa\SDispatch\Scripts'
DEFAULT_EDIT = 'C:\Program Files\Notepad++\Notepad++.exe'

# ANSI Escape Color List
# Intensity    0        1        2        3        4        5        6        7
# ------------------------------------------------------------------------------------
# Normal       Black    Red      Green    Yellow   Blue     Magenta  Cyan     White
# Bright       Black    Red      Green    Yellow   Blue     Magenta  Cyan     White

class String
    ANSI_DARK_RED = "\e[0m\e[31m"
    ANSI_DARK_GREEN = "\e[0m\e[32m"
    ANSI_DARK_YELLOW = "\e[0m\e[33m"
    ANSI_DARK_BLUE = "\e[0m\e[34m"
    ANSI_DARK_MAGENTA = "\e[0m\e[35m"
	ANSI_DARK_CYAN = "\e[0m\e[36m"
	ANSI_DARK_WHITE = "\e[0m\e[37m"
    ANSI_RED = "\e[1m\e[31m"
    ANSI_GREEN = "\e[1m\e[32m"
    ANSI_YELLOW = "\e[1m\e[33m"
    ANSI_BLUE = "\e[1m\e[34m"
    ANSI_MAGENTA = "\e[1m\e[35m"
	ANSI_CYAN = "\e[1m\e[36m"
	ANSI_WHITE = "\e[1m\e[37m"
	ANSI_END = "\e[0m"
	
    def dark_red; colorize(self, "#{ANSI_DARK_RED}"); end
    def dark_green; colorize(self, "#{ANSI_DARK_GREEN}"); end
    def dark_yellow; colorize(self, "#{ANSI_DARK_YELLOW}"); end
    def dark_blue; colorize(self, "#{ANSI_DARK_BLUE}"); end
    def dark_magenta; colorize(self, "#{ANSI_DARK_MAGENTA}"); end
	def dark_cyan; colorize(self, "#{ANSI_DARK_CYAN}"); end
	def dark_white; colorize(self, "#{ANSI_DARK_WHITE}"); end
    def red; colorize(self, "#{ANSI_RED}"); end
    def green; colorize(self, "#{ANSI_GREEN}"); end
    def yellow; colorize(self, "#{ANSI_YELLOW}"); end
    def blue; colorize(self, "#{ANSI_BLUE}"); end
    def magenta; colorize(self, "#{ANSI_MAGENTA}"); end
	def cyan; colorize(self, "#{ANSI_CYAN}"); end
	def white; colorize(self, "#{ANSI_WHITE}"); end
    def colorize(text, color_code)  "#{color_code}#{text}#{ANSI_END}" end
end

def show_end()
	puts String::ANSI_MAGENTA
	print "\04"
	print String::ANSI_END
end

def run_in_color(cmd)
	print String::ANSI_CYAN
	system(cmd)
	print String::ANSI_END
end

def vaa_dir(pattern)
	if check_single(pattern)
		arr_vaa = enum_vaa_names(pattern)
		dir = SCRIPTS_ROOT + "\\#{arr_vaa[0]}"
		cmd = "explorer.exe \"#{dir}\""
		puts "Open the directory: #{dir}..."
		if File.directory?(dir)
			system(cmd)
		else
			puts "Path not exist: #{dir}"
		end
	else
		puts "Error: Please refine your pattern."
	end
end

def vaa_logfilename(vaa_name)
	dir = SCRIPTS_ROOT + "\\#{vaa_name}\\Log"
	if File.directory?(dir)
		logFile = nil
		lastTime = nil
		Dir.foreach(dir) { |f|
			file = dir + "\\" + f
			if not File.directory?(file)
				if lastTime == nil or File.stat(file).mtime > lastTime
					lastTime = File.stat(file).mtime
					logFile = file
				end
			end
		}
	end
	return logFile
end

def show_log(pattern)
	if check_single(pattern)
		arr_vaa = enum_vaa_names(pattern)
		dir = SCRIPTS_ROOT + "\\#{arr_vaa[0]}\\Log"
		if File.directory?(dir)
			logFile = vaa_logfilename(arr_vaa[0])
			if logFile == nil
				puts "Error: No log file found in #{dir}."
			else
				puts "View log of #{arr_vaa[0]}: #{logFile}..."
				cmd = "exec \"#{DEFAULT_EDIT}\" -ro \"#{logFile}\""
				system(cmd)
			end
		else
			puts "Path not found: #{dir}"
		end
	else
		puts "Error: Please refine your pattern."
	end
end

def commit_vaa(pattern)
	if check_single(pattern)
		arr_vaa = enum_vaa_names(pattern)
		dir = SCRIPTS_ROOT + "\\#{arr_vaa[0]}"
		puts "Commit changes in #{dir}..."
		cmd = "svn commit -m \"VAA #{arr_vaa[0]} Updated\" #{dir}"
		system(cmd)
	else
		puts "Error: Please refine your pattern."
	end
end

def edit_vaa(pattern, lineno)
	if check_single(pattern)
		arr_vaa = enum_vaa_names(pattern)
		dir = SCRIPTS_ROOT + "\\#{arr_vaa[0]}"
		arr = Array.new
		Dir.foreach(dir) { |x|
			if not File.directory?(x) and File.extname(x).upcase() == ".VBS"
				arr.push(x)
			end
		}
		
		script = nil
		case arr.count
		when 0
			puts "Error: No VBScript file found in #{dir}"
		when 1
			script = arr[0]
		else
			arr.each { |x|
				if x.upcase() == pattern.upcase() + ".VBS"
					script = x
					break
				end
			}
			if script == nil
				puts "Error: more than one VBScript file found, please check."
				arr.each { |x|
					puts x
				}
			end
		end
		
		if script != nil
			script = dir + "\\" + script
			puts "Edit Script: #{script}..."
			cmd = "exec \"#{DEFAULT_EDIT}\" -n#{lineno.to_s} \"#{script}\""
			system(cmd)
		end
	else
		puts "Error: Please refine your pattern."
	end
end

def vaa_scriptname(vaa_name)
	dir = SCRIPTS_ROOT + "\\#{vaa_name}"
	arr = Array.new
	Dir.foreach(dir) { |x|
		if not File.directory?(x) and File.extname(x).upcase() == ".VBS"
			arr.push(x)
		end
	}
	
	script = nil
	case arr.count
	when 0
		return nil
	when 1
		script = arr[0]
	else
		arr.each { |x|
			if x.upcase() == vaa_name.upcase() + ".VBS"
				script = x
				break
			end
		}
		if script == nil
			puts "Error: more than one VBScript file found, please check."
			arr.each { |x|
				puts x
			}
		end
	end
	
	if script != nil
		return dir + "\\" + script
	else
		return nil
	end
end

def vaa_configname(vaa_name)
	dir = SCRIPTS_ROOT + "\\#{vaa_name}"
	arr = Array.new
	Dir.foreach(dir) { |x|
		if not File.directory?(x) and File.extname(x).upcase() == ".CFG"
			arr.push(x)
		end
	}
	
	script = nil
	case arr.count
	when 0
		return nil
	when 1
		script = arr[0]
	else
		arr.each { |x|
			if x.upcase() == vaa_name.upcase() + ".CFG"
				script = x
				break
			end
		}
		if script == nil
			puts "Error: more than one VBScript file found, please check."
			arr.each { |x|
				puts x
			}
		end
	end
	
	if script != nil
		return dir + "\\" + script
	else
		return nil
	end
end

def run_vaa(pattern, key, files, extargs)
	if check_single(pattern)
		calendar = 'Common/NoHoliday/NoTrigger'
		arr_vaa = enum_vaa_names(pattern)
		dir = SCRIPTS_ROOT + "\\#{arr_vaa[0]}"
		script = vaa_scriptname(arr_vaa[0])
		config = vaa_configname(arr_vaa[0])
		
		if config != nil
			inifile = IniFile.load(config)
			if inifile != nil
				calendar = inifile['DEFAULT']['Calendar']			
			end
		end
		
		if script != nil
			base_name = File.basename(script, File.extname(script))
			puts "Run Script: #{script}..."
			cmd = "cscript //Nologo \"#{script}\" 1000 #{SCRIPT_ID} #{base_name} \"#{dir}\" \\\\#{Socket.gethostname}\\config\\holiday.vht \"#{calendar}\" sdispatch \"\" \"#{key}\" \"#{files}\" #{extargs}"
			puts "CMD Option: #{cmd}"
			puts "------------------------------"
			system(cmd)
			puts "------------------------------"
		else
			puts "Error: No relavant VBScript found for #{pattern}."
		end
	else
		puts "Error: Please refine your pattern."
	end
end

def check_single(pattern)
	if pattern.upcase() == "ALL"
		pattern = "*"
	end
	arr = enum_vaa_names(pattern)
	if arr.count == 1
		return true
	else
		list_vaa(pattern)
		return false
	end
end


def list_vaa(pattern)
	if pattern.upcase() == "ALL"
		pattern = "*"
	end
	arr = enum_vaa_names(pattern)
	i = 0
	puts "Listing all VAAs like '#{pattern}':"
	puts "------------------------------"
	if arr.count > 0
		arr.each { |x|
			i = i + 1
			puts "#{i.to_s.rjust(3)} - #{x}"
		}
	else
		puts "(None)"
	end
	puts "------------------------------"
	puts "Total #{i} found."
end

def enum_vaa_names(pattern)
	arr_vaa = Array.new
	Dir.foreach(SCRIPTS_ROOT) { |x|
		if x != "." and x != ".." and x.match(/^[A-Z]/) != nil
			if File.fnmatch?(pattern, x, File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_CASEFOLD)
				arr_vaa.push(x)
			end
		end
	}
	return arr_vaa
end

def get_vaa_directory(pattern)
	arr_vaa = enum_vaa_names(pattern)
	if arr_vaa.count == 1
		dir = SCRIPTS_ROOT + "\\" + arr_vaa[0]
		return dir
	else
		return nil
	end
end

def search_in_file(file, pattern, filename_color, lineno_color, match_color)
	total = 0
	line_no = 0
	IO.foreach(file) { |line|
		line_no = line_no + 1
		if line.match(pattern) != nil
			found = line.gsub(/#{pattern}/) { |x| "#{match_color}#{x}#{String::ANSI_END}" }
			found = found.strip()
			puts "#{filename_color}#{File.basename(file)}#{String::ANSI_END} (#{lineno_color}#{line_no}#{String::ANSI_END}) #{found}"
			total = total + 1
		end
	}
	return total
end

def search_content(vaa_pattern, key_pattern)
	if vaa_pattern.upcase() == "ALL"
		vaa_pattern = "*"
	end
	arr = enum_vaa_names(vaa_pattern)
	nfile = 0
	if arr.count > 0
		arr.each { |x|
			file = vaa_scriptname(x)
			if file != nil
				if nfile % 2 == 0
					filename_color = String::ANSI_YELLOW
					lineno_color = String::ANSI_WHITE
					match_color = String::ANSI_RED
				else
					filename_color = String::ANSI_DARK_YELLOW
					lineno_color = String::ANSI_WHITE
					match_color = String::ANSI_RED
				end
				
				if search_in_file(file, key_pattern, filename_color, lineno_color, match_color) > 0
					nfile = nfile + 1
				end
			end

			file = vaa_logfilename(x)
			if file != nil
				if nfile % 2 == 0
					filename_color = String::ANSI_YELLOW
					lineno_color = String::ANSI_WHITE
					match_color = String::ANSI_RED
				else
					filename_color = String::ANSI_DARK_YELLOW
					lineno_color = String::ANSI_WHITE
					match_color = String::ANSI_GREEN
				end
				
				if search_in_file(file, key_pattern, filename_color, lineno_color, match_color) > 0
					nfile = nfile + 1
				end
			end
		}
	else
		puts "No VAA matches #{vaa_pattern}."
	end
end

def help
	puts "vaa - VAA Commands"
	puts "usage: vaa COMMAND [ARG1 [ARG2 [ARG3...]]]"
	puts "COMMAND:"
	puts "  list   - list all VAAs"
	puts "  edit   - edit a VAA"
	puts "  dir    - open the directory of VAA"
	puts "  run    - run a VAA"
	puts "  log    - show the latest log of VAA"
	puts "  add    - add a new VAA"
	puts "  find   - find content in matched VAA(s)"
	puts "  commit - commit changes to SVN"
end

def main
	if ARGV.size < 2
		help()
		exit
	end
	
	cmd = ARGV[0]
	vaa = ARGV[1]
	
	if not File.directory?(SCRIPTS_ROOT)
		puts "The root directory of scripts does not exist."
		exit
	end
	
	case cmd
	when "list"
		list_vaa(vaa)
	when "log"
		show_log(vaa)
	when "edit"
		lineno = 0
		if ARGV.size >= 3
			lineno = ARGV[2].to_i
		end
		edit_vaa(vaa, lineno)
	when "dir"
		vaa_dir(vaa)
	when "run"
		key = ""
		files = Array.new
		extargs = Array.new
		
		if ARGV.size >= 3
			i = 2
			if ARGV[i].start_with?('//')
				extargs.push(ARGV[i])
			else
				key = ARGV[i]
			end
		end
		
		if ARGV.size >= 4
			i = 3
			while i < ARGV.size
				if File.exist?(ARGV[i]) and not File.directory?(ARGV[i])
					files.push(ARGV[i])
				else
					if ARGV[i].start_with?('~')
						files.push(ARGV[i])
					else
						extargs.push(ARGV[i])
					end
				end
				i = i + 1
			end
		end
		run_vaa(vaa, key, files.join('|'), extargs.join(' '))
	when "find"
		if ARGV.size >= 3
			key = ARGV[2]
			search_content(vaa, key)
		else
			puts "Error: miss a parameter in pattern to search."
		end
	when "commit"
		commit_vaa(vaa)
	end
	
	show_end()
end

main
